package com.yanqu.road.server.manger.player;

import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.disperseGold.DisperseGoldGroupUser;
import com.yanqu.road.entity.disperseGold.DisperseGoldInfo;
import com.yanqu.road.entity.enums.eMailType;
import com.yanqu.road.entity.log.LogDispersePush;
import com.yanqu.road.entity.player.PlayerState;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.logic.bussiness.player.UserDisperseGoldBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.DisperseGoldPb;
import com.yanqu.road.pb.cross.disperseGold.CrossDisperseGoldProto;
import com.yanqu.road.pb.disperseGold.DisperseGoldProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.disperseGold.DisperseGoldModule;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.Cross3Protocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.text.MessageFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 散财
 */
public class DisperseGoldMgr extends TempMgr {
    private static Logger logger = LogManager.getLogger(DisperseGoldMgr.class);

    private static Map<Long, List<DisperseGoldInfo>> disperseGoldMap;

    private static RandomHelper random = new RandomHelper();

    private static Object lock = new Object();

    /**
     * 散财最大id
     */
    private static AtomicLong disperseId;

    @Override
    public boolean reloadData() {
        disperseGoldMap = UserDisperseGoldBussiness.getDisperseGoldMap();
        StringBuffer serverId = new StringBuffer( "" + GameServer.getInstance().getServerId());
        //玩家编号15位
        while (serverId.length() < 15) {
            serverId.append(0);
        }
        Long maxDisperseId = UserDisperseGoldBussiness.getMaxDisperseId(GameServer.getInstance().getServerId());
        if (maxDisperseId == 0) {
            //玩家编号15位
            while (serverId.length() < 15) {
                serverId.append(0);
            }
            disperseId = new AtomicLong(Long.valueOf(serverId.toString()));
        }else {
            disperseId = new AtomicLong(maxDisperseId);
        }
        return true;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        for (List<DisperseGoldInfo> infos : disperseGoldMap.values()) {
            if (infos == null) {
                continue;
            }
            Iterator<DisperseGoldInfo> iterator = infos.iterator();
            while (iterator.hasNext()) {
                DisperseGoldInfo info = iterator.next();
                if(info.isInsertOption()){
                    UserDisperseGoldBussiness.addDisperseGold(info);
                }else if(info.isUpdateOption()){
                    UserDisperseGoldBussiness.updateDisperseGold(info);
                }
                // 已经发送邮件就可以从内存中移除
                if (info.isSendEmail() && !info.isDirty()) {
                    iterator.remove();
                }
            }
        }
        return true;
    }

    /**
     * 领取送财奖励
     * @param disperseGoldInfo
     * @param earnSpeed  玩家自己的赚速
     * @return
     */
    public static Property getDisperseGoldReward(DisperseGoldInfo disperseGoldInfo, BigInteger earnSpeed) {
        int totalGold = 0;
        int totalSecond = 0;
        String[] honoraryTitles = disperseGoldInfo.getHonoraryTitles().split(",");
        for (String honoraryTitle : honoraryTitles) {
            int goodsId = Integer.valueOf(honoraryTitle);
            GoodsInfo goods = GoodsMgr.getGoodsById(goodsId);
            String[] params = goods.getExtendParam().split("\\|");
            if (params.length < 4) {
                logger.error("称号参数配置错误");
                return null;
            }
            int gold = random.next(Integer.valueOf(params[0]), Integer.valueOf(params[1]));
            totalGold += gold;
            int second = random.next(Integer.valueOf(params[2]), Integer.valueOf(params[3]));
            totalSecond += second;

        }
        //2.7又不上了 注释掉吧 散财机制修改
//        GoodsInfo honoraryTitle = null;
//        for (String title : honoraryTitles) {
//            int goodsId = Integer.valueOf(title);
//            GoodsInfo goods = GoodsMgr.getGoodsById(goodsId);
//            List<BigInteger> params = goods.getParamList();
//            if (honoraryTitle == null || honoraryTitle.getParamList().get(3).compareTo(params.get(3)) < 0) {
//                honoraryTitle = goods;
//            }
//
//        }
//        String[] params = honoraryTitle.getExtendParam().split("\\|");
//        if (params.length < 4) {
//            logger.error("称号参数配置错误");
//            return null;
//        }
//        int gold = random.next(Integer.valueOf(params[0]), Integer.valueOf(params[1]));
//        totalGold += gold;
//        int second = random.next(Integer.valueOf(params[2]), Integer.valueOf(params[3]));
//        totalSecond += second;
        //最多可获得元宝数
        totalGold = totalGold > GameConfig.DISPERSE_GOLD_MAX_GOLD ? GameConfig.DISPERSE_GOLD_MAX_GOLD : totalGold;
        //最多可获得银两系数
        totalSecond = totalSecond > GameConfig.DISPERSE_GOLD_MAX_SILVER ? GameConfig.DISPERSE_GOLD_MAX_SILVER : totalSecond;

        BigInteger silver = earnSpeed.multiply(BigInteger.valueOf(totalSecond));
        // 同步到总领取奖励
        synchronized (lock) {
            Property property = PropertyHelper.parseStringToProperty(disperseGoldInfo.getReward());
            if (property == null) {
                property = new Property();
            }
            property.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(totalGold));
            property.addProperty(GameConfig.GAME_MONEY_SILVER, silver);
            disperseGoldInfo.setReward(PropertyHelper.parsePropertyToString(property));
            disperseGoldInfo.setPlayerNum(disperseGoldInfo.getPlayerNum()+1);
        }

        Property property = new Property();
        property.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(totalGold));
        property.addProperty(GameConfig.GAME_MONEY_SILVER, silver);

        return property;
    }


    /**
     * 获取送财信息
     * @param userId
     * @param disperseId
     * @return
     */
    public static DisperseGoldInfo getDisperseGoldInfo(long userId, long disperseId) {
        List<DisperseGoldInfo> disperseGoldList = getDisperseGoldList(userId);
        if (disperseGoldList == null) {
            disperseGoldList = new ArrayList<>();
            disperseGoldMap.put(userId, disperseGoldList);
        }
        for (DisperseGoldInfo info : disperseGoldList) {
            if (info.getDisperseId() == disperseId) {
                return info;
            }
        }
        return null;
    }

    /**
     * 获取送财信息
     * （效率略低点）
     */
    public static DisperseGoldInfo getDisperseGoldInfo(long disperseId) {
        for (List<DisperseGoldInfo> infos : disperseGoldMap.values()) {
            for (DisperseGoldInfo info : infos) {
                if (info.getDisperseId() == disperseId) {
                    return info;
                }
            }
        }
        return null;
    }

    /**
     * 发送送财信息
     *
     * @param userInfo
     * @param manifesto
     */
    public static void sendDisperseGoldMsg(UserInfo userInfo, String manifesto, List<Integer> honoraryTitleList, Set<Long> crossServerIds, List<DisperseGoldGroupUser> groupUserList,
                                           String assistantSkin, String badge, int curioPrivilegeItemId) {
        long userId = userInfo.getUserId();
        long serverId = GameServer.getInstance().getServerId();
//        List<DisperseGoldInfo> disperseGoldList = getDisperseGoldList(userId);
//        if (disperseGoldList == null) {
//            disperseGoldList = new ArrayList<>();
//            disperseGoldMap.put(userId, disperseGoldList);
//        }
        DisperseGoldInfo info = new DisperseGoldInfo();
        long id = disperseId.addAndGet(1);
        info.setDisperseId(id);
        info.setUserId(userId);
        info.setManifesto(manifesto);
        info.setBeginTime(System.currentTimeMillis());
        info.setReward("");
        info.setPrivilege(String.valueOf(curioPrivilegeItemId));
        // 散财用户
        info.setReceiveUserList(groupUserList);
        StringBuilder honoraryTitles = new StringBuilder();
        honoraryTitleList.forEach(goodId -> {
            honoraryTitles.append(goodId);
            honoraryTitles.append(",");
        });
        if (honoraryTitles.length() > 0) {
            honoraryTitles.deleteCharAt(honoraryTitles.length() - 1);
        }
        info.setHonoraryTitles(honoraryTitles.toString());
        info.setServerId(serverId);
        info.setEarnSpeed(userInfo.getEarnSpeed());
        info.setChannelId(ServerListMgr.getChannelId(GameServer.getInstance().getServerId()));
        info.setAssistantSkin(assistantSkin);
        info.setBadge(badge);
        info.setInsertOption();
//        disperseGoldList.add(info);

        UserBaseInfo userBaseInfo = UserMgr.getUserBaseInfo(userId, serverId);
        // 计算是否需要跨地区
        boolean needCrossChannel = false;
        int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
        for (long crossServerId : crossServerIds) {
            int tmpChannelId = ServerListMgr.getChannelId(crossServerId);
            if (channelId != tmpChannelId) {
                needCrossChannel = true;
                break;
            }
        }

        if (needCrossChannel) {
            // 跨地区送财
            CrossDisperseGoldProto.CrossDisperseGoldMsg.Builder crossMsg = DisperseGoldPb.parseCrossDisperseGoldMsg(info, userBaseInfo, crossServerIds, groupUserList);
            crossMsg.setSyncChannel(true);
            YanQuMessage pbMessage = YanQuMessageUtils.buildMessage(Cross3Protocol.C3_DISPERSE_GOLD_SEND_INFO, crossMsg);
            GamePlayerMgr.sendPacket(0, pbMessage);
        } else if (!crossServerIds.isEmpty() || groupUserList.size() != 0) {
            // 跨服送财
            CrossDisperseGoldProto.CrossDisperseGoldMsg.Builder crossMsg = DisperseGoldPb.parseCrossDisperseGoldMsg(info, userBaseInfo, crossServerIds, groupUserList);
            YanQuMessage pbMessage = YanQuMessageUtils.buildMessage(Protocol.C_DISPERSE_GOLD_SEND_INFO, crossMsg);
            GamePlayerMgr.sendPacket(0, pbMessage);
        }

    }



    /**
     * 向全服发送
     */
    private static void sendWorldMessage(DisperseGoldProto.DisperseGoldFindGodMsg.Builder msg) {
        AutoLogMgr.add(new LogDispersePush(msg.getDisperseId(), msg.getUserId(), msg.getPlayerInfo().getServerId(), msg.getManifesto()));
        // 按玩家发送
        for (GamePlayer player : GamePlayerMgr.getCopyPlayerList()) {
            if (player == null || player.getState() != PlayerState.ONLINE) {
                continue;
            }
            player.getModule(DisperseGoldModule.class).syncDisperseMsg(msg);
        }
    }

    /**
     * 向指定用户发送
     */
    private static void sendWorldMessage(Set<Long> userIdList, DisperseGoldProto.DisperseGoldFindGodMsg.Builder msg) {
        AutoLogMgr.add(new LogDispersePush(msg.getDisperseId(), msg.getUserId(), msg.getPlayerInfo().getServerId(), msg.getManifesto()));
        // 按玩家发送
        for (Long userId : userIdList) {
            GamePlayer onlinePlayer = GamePlayerMgr.getOnlinePlayer(userId);
            if (onlinePlayer == null) {
                // 不在线不用处理
                continue;
            }
            onlinePlayer.getModule(DisperseGoldModule.class).syncDisperseMsg(msg);
        }
    }


    /**
     * 获取时限内的散财记录
     * @return
     */
    public static List<DisperseGoldInfo> sendDisperseGold(long myUserId) {
        if (isEmptyMap()) {
            return null;
        }
        List<DisperseGoldInfo> list = new ArrayList<>();
        disperseGoldMap.forEach((userId,infos)->{
            if (infos != null){
                for (DisperseGoldInfo info : infos) {
                    //已经发送邮件
                    if (info.isSendEmail()){
                        continue;
                    }
                    //检查是否结束了
                    if (isDisperseGoldEnd(info)) {
                        continue;
                    }
                    // 判断下是否有名单
                    if (!info.getReceiveUserList().isEmpty()
                            && info.getReceiveUserList().stream().noneMatch(disperseGoldGroupUser -> myUserId == disperseGoldGroupUser.getUserId())) {
                        continue;
                    }
                    list.add(info);
                }
            }
        });
        return list;
    }

    /**
     * 获取玩家散财记录
     * @param userId
     * @return
     */
    public static List<DisperseGoldInfo> getDisperseGoldList(long userId) {
        if (isEmptyMap()) {
            return null;
        }
        return disperseGoldMap.get(userId);
    }

    /**
     * 检测送财结果
     */
    public static void checkDisperseGold() {
        if (isEmptyMap()) {
            return;
        }

        disperseGoldMap.forEach((userId,infos)->{
            if (infos != null){
                Iterator<DisperseGoldInfo> iterator = infos.iterator();
                while (iterator.hasNext()) {
                    DisperseGoldInfo info = iterator.next();

                    //已经发送邮件
                    if (info.isSendEmail()){
                        continue;
                    }
                    //检查是否结束了
                    if (!isDisperseGoldEnd(info)){
                        continue;
                    }
                    if (info.getServerId() == GameServer.getInstance().getServerId()) {
                        //等待一次才发送,确保跨服送财都结束了
                        if (!info.isWait()){
                            info.setWait(true);
                            continue;
                        }
                        //发送邮件
                        UserInfo userInfo = UserMgr.getUserInfo(info.getUserId());
                        Property property = PropertyHelper.parseStringToProperty(info.getReward());
                        if (property == null) {
                            property = new Property();
                        }
                        BigInteger gold = property.getCountByGoodsId(GameConfig.GAME_MONEY_INGOTS);
                        BigInteger silver = property.getCountByGoodsId(GameConfig.GAME_MONEY_SILVER);
                        String mailTitle = MultipleLanguageMgr.getContent(MailManager.DISPERSE_GOLD_REWARD_TITLE, userInfo.getLanguage());
                        String mailContent = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.DISPERSE_GOLD_REWARD_CONTENT, userInfo.getLanguage()), info.getPlayerNum(), gold, silver);
                        MailManager.sendMail(info.getUserId(), eMailType.SYSTEM.getValue(), "", mailContent, mailTitle);
                        info.setSendEmail(true);
                    } else {
                        boolean needChannel = ServerListMgr.getChannelId(GameServer.getInstance().getServerId())
                                != ServerListMgr.getChannelId(info.getServerId());
                        int msgCode = needChannel ? Cross3Protocol.C3_DISPERSE_GOLD_SEND_RESULT // 返回给其他地区
                                : Protocol.C_DISPERSE_GOLD_SEND_RESULT; // 返回给本地区其他服
                        CrossDisperseGoldProto.CrossDisperseGoldInfoMsg.Builder crossMsg = DisperseGoldPb.parseCrossDisperseGoldInfoMsg(info);
                        YanQuMessage pbMessage = YanQuMessageUtils.buildMessage(msgCode, crossMsg);
                        GamePlayerMgr.sendPacket(0, pbMessage);
                        info.setSendEmail(true);
                    }

                }
            }
        });
    }


    public static boolean isDisperseGoldEnd(DisperseGoldInfo disperseGoldInfo) {
        String honoraryTitles = disperseGoldInfo.getHonoraryTitles();
        int honoraryNum = honoraryTitles.split(",").length;
        // 距离开始送财时间间隔
        long time = (System.currentTimeMillis() - disperseGoldInfo.getBeginTime()) / 1000;
        // 时间限制=送财时间限制+播放动画初始时间+播放动画增长时间*称号个数
        int duration = GameConfig.DISPERSE_GOLD_TIME + GameConfig.DISPERSE_GOLD_PLAY_DURATION + GameConfig.DISPERSE_GOLD_PLAY_EXTEND * (honoraryNum - 1);
        return time > duration;
    }

    private static boolean isEmptyMap() {
        return disperseGoldMap == null || disperseGoldMap.isEmpty();
    }

    /**
     * 跨服,收到送财信息
     */
    public static void crossDisperseGoldInfo(UserBaseInfo userBaseInfo, DisperseGoldInfo info, boolean sendAll, Set<Long> userIdList) {
        info.getReceiveUserList().removeIf(groupUser -> groupUser.getServerId() != GameServer.getInstance().getServerId());
        List<DisperseGoldInfo> disperseGoldList = getDisperseGoldList(info.getUserId());
        if (disperseGoldList == null) {
            disperseGoldList = new ArrayList<>();
            disperseGoldMap.put(info.getUserId(), disperseGoldList);
        }
        info.setInsertOption();
        disperseGoldList.add(info);

        DisperseGoldProto.DisperseGoldFindGodMsg.Builder msg = DisperseGoldPb.parseDisperseGoldFindGodMsg(info, userBaseInfo);
        if (sendAll) {
            sendWorldMessage(msg);
        } else {
            sendWorldMessage(userIdList, msg);
        }
    }

    /**
     * 跨服,接收送财结果
     */
    public synchronized static void crossDisperseGoldResult(DisperseGoldInfo crossInfo) {
        List<DisperseGoldInfo> disperseGoldList = getDisperseGoldList(crossInfo.getUserId());
        if (disperseGoldList == null) {
            return;
        }
        DisperseGoldInfo info = null;
        for (DisperseGoldInfo disperseGoldInfo : disperseGoldList) {
            if (crossInfo.getDisperseId() == disperseGoldInfo.getDisperseId()) {
                info = disperseGoldInfo;
                break;
            }
        }
        if (info == null) {
            return;
        }
        info.setPlayerNum(info.getPlayerNum()+crossInfo.getPlayerNum());
        Property reward = PropertyHelper.parseStringToProperty(info.getReward());
        Property crosssReward = PropertyHelper.parseStringToProperty(crossInfo.getReward());
        if(null == reward){
            reward = new Property();
        }
        reward.addProperty(crosssReward);
        info.setReward(PropertyHelper.parsePropertyToString(reward));
    }
}
